import { Graph, Node, StringExt } from '@antv/x6';
import styled from '@emotion/styled';
import { Popover } from 'antd';
import { FC } from 'react';

import PlusIcon from '@/assets/icons/plus.svg';
import { colors } from '@/config/theme';
import { NODE_LIST, NODE_TYPE } from '@/constants/config';
import { useGraph } from '@/hooks/useGraph';
import { createGraphNode, createPortNameWithNodeType } from '@/utils/graph';

import { BaseNodeContent } from '../..';
import { BaseNodeProps } from '../../define';

const NodeListDiv = styled.div`
  .base-node-content {
    transition: all 0.1s;
    &:hover {
      color: ${colors.primary[500]};
      transform: scale(1.04);

      svg {
        fill: ${colors.primary[500]};
      }
    }
  }
`;

export const CreateNextNode: FC<BaseNodeProps<any>> = memo((props) => {
  const { graph } = useGraph();
  const getNextNodePosition = (node: Node, graph: Graph, dx = 300, dy = 100) => {
    // 找出画布中以该起始节点为起点的相关边的终点id集合
    const downstreamNodeIdList: string[] = [];
    graph.getEdges().forEach((edge) => {
      const originEdge = edge.toJSON()?.data;
      if (originEdge?.source === node.id) {
        downstreamNodeIdList.push(originEdge.target);
      }
    });
    // 获取起点的位置信息
    const position = node.getPosition();
    let minX = Infinity;
    let maxY = -Infinity;
    graph.getNodes().forEach((graphNode) => {
      if (downstreamNodeIdList.indexOf(graphNode.id) > -1) {
        const nodePosition = graphNode.getPosition();
        // 找到所有节点中最左侧的节点的x坐标
        if (nodePosition.x < minX) {
          minX = nodePosition.x;
        }
        // 找到所有节点中最x下方的节点的y坐标
        if (nodePosition.y > maxY) {
          maxY = nodePosition.y;
        }
      }
    });

    return {
      x: minX !== Infinity ? minX : position.x + dx,
      y: maxY !== -Infinity ? maxY + dy : position.y
    };
  };

  const createNode = (type: keyof typeof NODE_TYPE, graph: Graph, position?: { x: number; y: number }) => {
    const nodeConfig = createGraphNode(type, {
      nodeType: type,
      ...NODE_LIST[type]
    });
    const node = graph.createNode(nodeConfig);

    if (position) {
      node.setPosition(position.x, position.y);
    }

    const newNode = graph.addNode(node);
    return newNode;
  };

  const createNextNode = (nodeType: keyof typeof NODE_TYPE) => {
    const node = props.node!;
    if (graph) {
      // 获取下游节点的初始位置信息
      const position = getNextNodePosition(node, graph);
      // 创建下游节点
      const newNode = createNode(nodeType, graph, position);
      const source = node.id;
      const target = newNode.id;
      const data = node.getData();
      // 创建该节点出发到下游节点的边
      const edge = {
        id: StringExt.uuid(),
        shape: NODE_TYPE.BASE_EDGE,
        source: {
          cell: source,
          port: createPortNameWithNodeType(data.nodeType, 'right')
        },
        target: {
          cell: target,
          port: createPortNameWithNodeType(nodeType, 'left')
        },
        zIndex: -1,
        data: {
          source,
          target
        }
      };
      if (graph) {
        graph.addEdge(edge);
      }
    }
  };

  const nodeConfig = !props.nodeType ? null : NODE_LIST[props.nodeType];

  return (
    <Popover
      content={
        <NodeListDiv className="flex flex-col gap-2 node-list">
          {nodeConfig?.nextNodeList?.map((nodeType: keyof typeof NODE_TYPE) => (
            <BaseNodeContent
              className="w-110"
              key={nodeType}
              onClick={(e) => {
                createNextNode(nodeType);
                e.stopPropagation();
              }}
              nodeName={NODE_LIST[nodeType].nodeName}
              nodeType={nodeType}
            />
          ))}
        </NodeListDiv>
      }
      className="popover-node-list"
      trigger="click">
      {!nodeConfig?.nextNodeList?.length ? (
        <div></div>
      ) : (
        <div onClick={(e) => e.stopPropagation()} className="add-node cursor-pointer">
          <div className="add-node-btn">
            <PlusIcon width={12} height={12} color={colors.gray[600]} name="plus" className="mr-8" />
          </div>
        </div>
      )}
    </Popover>
  );
});
